require(readr, quietly = TRUE)
require(purrr, quietly = TRUE)
require(stringr, quietly = TRUE)
require(knitr, quietly = TRUE)
require(kableExtra, quietly = TRUE)
require(texreg, quietly = TRUE)

options(knitr.table.format = "latex")
options(knitr.kable.NA = '\\texttt{NaN}')
options(knitr.kable.digits = 3)

dflt_kable_style <- purrr::partial(
  kable_styling
  , full_width = FALSE
  , position = "center"
  , font_size = 9L
  # , latex_options = c("HOLD_position", "repeat_header")
  # , latex_options = c("hold_position", "repeat_header")
  , latex_options = c("repeat_header")
  , repeat_header_continued = "\\textit{(Continued on next page...)}"
)

use_kable <- function(x, ...) {
  kab <- kable(x, ..., format = "latex", digits = 3, booktabs = TRUE, linesep = "")
  attr(kab, "data") <- x
  return(kab)
}

quick_kable <- function(...) {
  kab <- use_kable(...)
  data <- attr(kab, "data")
  out <- dflt_kable_style(kab)
  attr(out, "data") <- data
  return(out)
}


# custom kable write function
write_kable <- function(
    x
    , dir
    , overwrite = FALSE
    , position = NULL
    , .file.name = sub(".*\\\\label\\{([^{]+)\\}.*", "\\1", attr(x, "kable_meta")$caption, perl = TRUE)
    , .file.name.cleaning = c("^tab:" = "")
    , .file.extension = "tex"
    , .write = TRUE
    , .write.data = TRUE
) {
  if (!is.null(.file.name.cleaning))
    .file.name <- stringr::str_replace_all(.file.name, .file.name.cleaning)
  
  if (.write.data && !is.null(attr(x, "data")))
    readr::write_tsv(attr(x, "data"), file.path(dir, paste0(.file.name, ".tab")))
  
  latex <- as.character(x)
  if (!is.null(position))
    latex <- sub("(?<=\\\\begin\\{table\\})(\\[[^]]+\\])?(?=\n)", sprintf("[%s]", position), latex, perl = TRUE)
  
  fp <- file.path(dir, paste0(.file.name, ".", .file.extension))
  if (!file.exists(fp) || overwrite)
    readr::write_lines(latex, fp)
  
  return(x)
}

row_spec <- function(kable_input, ...) {
  data <- attr(kable_input, "data")
  out <- kableExtra::row_spec(kable_input, ...)
  attr(out, "data") <- data
  return(out)
}

group_rows <- function(kable_input, ...) {
  data <- attr(kable_input, "data")
  out <- kableExtra::group_rows(kable_input, ...)
  attr(out, "data") <- data
  return(out)
}

collapse_rows <- function(kable_input, ...) {
  data <- attr(kable_input, "data")
  out <- kableExtra::collapse_rows(kable_input, ...)
  attr(out, "data") <- data
  return(out)
}

add_header_above <- function(kable_input, ...) {
  data <- attr(kable_input, "data")
  out <- kableExtra::add_header_above(kable_input, ...)
  attr(out, "data") <- data
  return(out)
}

landscape <- function(kable_input, ...) {
  data <- attr(kable_input, "data")
  out <- kableExtra::landscape(kable_input, ...)
  attr(out, "data") <- data
  return(out)
}
